import time

import traceback

from globalval import globalVal
import threading
import schedule
import datetime
import builtins
from enum_type import re_bond_entrust_dictionary_dic
import sys
from utils import format_exception, error_print_prefix, get_formative_exception


def my_print(*args, sep=' ', end='', file=None, flush=None):
    arg_str_list = []
    for arg in args:
        arg_str_list.append(str(arg).replace('\n', 'NEWLINE'))
    arg_str = ' '.join(arg_str_list)
    builtins.print(arg_str)
    sys.stdout.flush()
    sys.stderr.flush()


print = my_print


def get_log():
    return globalVal.global_dict.get('log')


def get_api():
    return globalVal.global_dict.get('api')


@format_exception
def set_universe(security_list):
    get_api().set_universe(security_list)


@format_exception
def order_basket(entrust_list):
    return get_api().order_basket(entrust_list)


@format_exception
def order(security, amount, limit_price=None, price_type='A', entrust_direction="BUY", investunit_id=0, instance_id=0):
    return get_api().order(security, amount, limit_price, price_type, entrust_direction, investunit_id, instance_id)


@format_exception
def order_bond(security, amount, limit_price, entrust_direction, investunit_id=0, instance_id=0):
    """
    债券下单接口(委托方向暂只支持BOND_BUY,BOND_SELL,FINANCING,MARGIN)
    """

    if amount <= 0:
        print(error_print_prefix + ' 委托数量不合法，委托取消，请重新输入！')
    if entrust_direction not in re_bond_entrust_dictionary_dic.keys():
        raise Exception("委托方向  entrust_direction 字段输入有误，请检查！")
    return get_api().order(security, amount, limit_price, 'A', entrust_direction, investunit_id, instance_id,
                           futures_direction="OPEN")


@format_exception
def cancel_order(order_id):
    get_api().cancel_order(order_id)


@format_exception
def cancel_by_entrust_no(entrust_no):
    get_api().cancel_order_by_entrust_no(entrust_no)


@format_exception
def get_position(investunit_id=0, instance_id=0):
    return get_api().get_position(investunit_id, instance_id)


@format_exception
def get_opinstance(investunit_id=0, instance_id=0):
    return get_api().get_opinstance(investunit_id, instance_id)


@format_exception
def get_ext_orders(investunit_id=0, instance_id=0, request_num=100, entrust_state=None, is_order_by_python=False):
    return get_api().get_ext_orders(None, investunit_id, instance_id, request_num, entrust_state, is_order_by_python)


@format_exception
def get_ext_trades(investunit_id=0, instance_id=0, request_num=100, query_type='STOCK'):
    return get_api().get_ext_trades(None, investunit_id, instance_id, request_num, query_type)


@format_exception
def get_his_orders(begin_date, end_date, investunit_id=0, position_int=0, request_num=5000):
    return get_api().get_his_orders(begin_date, end_date, investunit_id, position_int, request_num)


@format_exception
def get_available_money(investunit_id=0, investunit_type='STOCK', market_no=1):
    return get_api().get_available_money(investunit_id, investunit_type, market_no)


@format_exception
def get_trader_time(code):
    return get_api().get_trade_time(code)


@format_exception
def get_min_price_interval(code_list=None):
    return get_api().get_min_price_interval(code_list)


@format_exception
def query_stock_fund(investunit_id=0):
    return get_api().query_stock_fund(investunit_id)


@format_exception
def get_history(count=5, frequency='1d', field='low', security_list=None, fq=None):
    return get_api().get_latest_history(count, frequency, security_list, fq)


@format_exception
def get_price(security=['600751.XSHG'], start_date='20150101', end_date='20151231', frequency='1d', fields=None,
              fq=None):
    return get_api().get_price_by_date(security, start_date, end_date, frequency, fields, fq)


@format_exception
def get_snapshots(contract_list):
    contract_list = contract_list if isinstance(contract_list, list) else [contract_list]
    return get_api().get_snapshot(contract_list)


@format_exception
def query_stock_fund(investunit_id=0):
    return get_api().query_stock_fund(investunit_id)


@format_exception
def run_interval(context, job, seconds=1, starttime=93000, endtime=140000):
    t = threading.Thread(target=_run_interval, args=(context, job, seconds, starttime, endtime), daemon=True)
    t.start()


@format_exception
def _run_interval(context, job, seconds=4, starttime=93000, endtime=140000):
    schedule.every(seconds).seconds.do(job, context)
    while True:
        n = datetime.datetime.now()
        nnum = n.hour * 10000 + n.minute * 100 + n.second
        if starttime <= nnum <= endtime:
            try:
                schedule.run_pending()
            except Exception as e:
                ne = traceback.format_exc()
                if not ne:
                    ne = str(e)
                    print(error_print_prefix + ne + '运行函数' + str(job))
                else:
                    print(error_print_prefix + get_formative_exception(ne))

        else:
            # print('nnum=', nnum, ' not in time range')
            pass
        sys.stdout.flush()
        sys.stderr.flush()
        time.sleep(seconds)
